package vip.xiaonuo.h5.royalty.modular.my.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.biz.modular.user.entity.BizUser;
import vip.xiaonuo.biz.modular.user.service.BizUserService;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.h5.royalty.modular.my.param.IncomeRecordParam;
import vip.xiaonuo.h5.royalty.modular.my.param.ModifyBankInfoParam;
import vip.xiaonuo.h5.royalty.modular.my.param.WithDrawParam;
import vip.xiaonuo.h5.royalty.modular.my.param.WithdrawRecordParam;
import vip.xiaonuo.h5.royalty.modular.my.service.MyService;

import vip.xiaonuo.h5.royalty.modular.my.vo.*;
import vip.xiaonuo.h5.royalty.system.profitsharebalance.entity.H5ProfitShareBalance;
import vip.xiaonuo.h5.royalty.system.profitsharebalance.service.H5ProfitShareBalanceService;
import vip.xiaonuo.h5.royalty.system.profitsharecreditrecord.service.H5ProfitShareCreditRecordService;
import vip.xiaonuo.h5.royalty.system.profitsharewithdrawrecord.entity.H5ProfitShareWithdrawRecord;
import vip.xiaonuo.h5.royalty.system.profitsharewithdrawrecord.service.H5ProfitShareWithdrawRecordService;

import vip.xiaonuo.h5.royalty.system.profitsharestatistics.entity.H5ProfitShareStatistics;
import vip.xiaonuo.h5.royalty.system.profitsharestatistics.service.H5ProfitShareStatisticsService;
import vip.xiaonuo.h5.royalty.system.profitsharebalancelog.entity.H5ProfitShareBalanceLog;
import vip.xiaonuo.h5.royalty.system.profitsharebalancelog.service.H5ProfitShareBalanceLogService;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 我的服务实现类
 */
@Slf4j
@Service
public class MyServiceImpl implements MyService {


    @Autowired
    private BizUserService bizUserService;

    @Autowired
    private H5ProfitShareBalanceService h5ProfitShareBalanceService;

    @Autowired
    private H5ProfitShareCreditRecordService h5ProfitShareCreditRecordService;

    @Autowired
    private H5ProfitShareStatisticsService h5ProfitShareStatisticsService;

    @Autowired
    private H5ProfitShareWithdrawRecordService withdrawRecordService;

    @Autowired
    private H5ProfitShareBalanceLogService h5ProfitShareBalanceLogService;


    @Override
    public MyInfoVo getMyInfo() {
        MyInfoVo result = new MyInfoVo();
        String loginUserId = StpUtil.getLoginIdAsString();
        BizUser bizUser = bizUserService.queryEntity(loginUserId);
        // 设置姓名
        result.setName(bizUser.getName());
        // 设置手机号（中间四位模糊处理）
        String phone = bizUser.getPhone();
        if (phone != null) {
            result.setPhone(phone.substring(0, 3) + "****" + phone.substring(7));
        }
        return result;
    }

    @Override
    public MyBalanceVo getBalance() {
        String loginUserId = StpUtil.getLoginIdAsString();
        LambdaQueryWrapper<H5ProfitShareBalance> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(H5ProfitShareBalance::getSharePartyId, loginUserId);
        H5ProfitShareBalance bal = h5ProfitShareBalanceService.getOne(queryWrapper);
        MyBalanceVo result = new MyBalanceVo();
        if (ObjUtil.isNotEmpty(bal)) {
            // 保留两位小数
            BigDecimal balance = bal.getAvailableBalance() != null ?
                    bal.getAvailableBalance().setScale(2, BigDecimal.ROUND_HALF_UP) :
                    BigDecimal.ZERO.setScale(2);
            result.setBalance(balance);

            // 检查银行卡信息是否完整
            boolean hasBankInfo = StrUtil.isNotBlank(bal.getBankAccount()) &&
                    StrUtil.isNotBlank(bal.getBankName()) &&
                    StrUtil.isNotBlank(bal.getRecipient());
            result.setHasBankInfo(hasBankInfo);

            if (hasBankInfo) {
                MyBalanceVo.BankInfo bankInfo = new MyBalanceVo.BankInfo();
                bankInfo.setBankName(bal.getBankName());
                bankInfo.setBankAccount(bal.getBankAccount());
                bankInfo.setOpeningBank(bal.getOpeningBank());
                bankInfo.setRecipient(bal.getRecipient());
                result.setBankInfo(bankInfo);
            }
        } else {
            log.error("未能查询到用户,id:{},余额默认显示0.00", loginUserId);
            result.setBalance(new BigDecimal("0.00"));
            result.setHasBankInfo(false);
        }
        return result;
    }

    @Override
    public IncomeRecordPage getIncomeRecords(IncomeRecordParam param) {
        IncomeRecordPage result = new IncomeRecordPage();

        // 获取当前登录用户ID
        String loginUserId = StpUtil.getLoginIdAsString();

        // 构建查询条件 - 使用统计表 H5ProfitShareStatistics
        LambdaQueryWrapper<H5ProfitShareStatistics> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(H5ProfitShareStatistics::getSharePartyId, loginUserId)
                .orderByDesc(H5ProfitShareStatistics::getStatisticsDate);

        // 根据参数添加过滤条件
        if (param.getLastId() != null && !param.getLastId().isEmpty()) {
            queryWrapper.lt(H5ProfitShareStatistics::getId, param.getLastId());
        }

        if (param.getStationId() != null && !param.getStationId().isEmpty()) {
            queryWrapper.eq(H5ProfitShareStatistics::getStationId, param.getStationId());
        }

        if (param.getStartTime() != null && !param.getStartTime().isEmpty() &&
                param.getEndTime() != null && !param.getEndTime().isEmpty()) {
            queryWrapper.ge(H5ProfitShareStatistics::getStatisticsDate, param.getStartTime())
                    .le(H5ProfitShareStatistics::getStatisticsDate, param.getEndTime());
        }

        // 查询符合条件的统计记录
        List<H5ProfitShareStatistics> statisticsList = h5ProfitShareStatisticsService.list(queryWrapper);

        // 计算累计入账金额（总分润金额）
        BigDecimal cumulative = statisticsList.stream()
                .map(H5ProfitShareStatistics::getTotalShareAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // 设置累计金额并格式化
        result.setCumulative(cumulative != null ? cumulative.setScale(2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO.setScale(2));

        // 设置总记录数
        result.setTotal(statisticsList.size());

        // 转换为VO列表
        List<IncomeRecordVo> incomeRecordList = statisticsList.stream().map(statistics -> {
            IncomeRecordVo vo = new IncomeRecordVo();
            vo.setProfitStatisticId(statistics.getId());
            vo.setOrgId(statistics.getOrgId());
            vo.setStationId(statistics.getStationId());
            // 设置服务费总计并格式化
            vo.setServiceFeeTotal(statistics.getTotalServiceFee() != null ?
                    statistics.getTotalServiceFee().setScale(2, BigDecimal.ROUND_HALF_UP) :
                    BigDecimal.ZERO.setScale(2));
            // 设置分润比例并格式化
            vo.setShareRatio(statistics.getShareRatio() != null ?
                    statistics.getShareRatio().setScale(2, BigDecimal.ROUND_HALF_UP) :
                    BigDecimal.ZERO.setScale(2));
            // 设置实际收入并格式化
            vo.setActualIncome(statistics.getTotalShareAmount() != null ?
                    statistics.getTotalShareAmount().setScale(2, BigDecimal.ROUND_HALF_UP) :
                    BigDecimal.ZERO.setScale(2));
            vo.setOrdersCount(statistics.getTotalOrderCount());
            // 设置入账时间（统计日期）
            if (statistics.getStatisticsDate() != null) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                vo.setInComeTime(simpleDateFormat.format(statistics.getStatisticsDate()));
            }
            return vo;
        }).collect(Collectors.toList());

        result.setList(incomeRecordList);

        return result;
    }

    @Override
    public void modifyBankInfo(ModifyBankInfoParam modifyBankInfoParam) {
        String loginUserId = StpUtil.getLoginIdAsString();

        // 查询用户余额记录
        LambdaQueryWrapper<H5ProfitShareBalance> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(H5ProfitShareBalance::getSharePartyId, loginUserId);
        H5ProfitShareBalance balance = h5ProfitShareBalanceService.getOne(queryWrapper);
        if (ObjUtil.isEmpty(balance)) {
            log.error("更新用户银行卡信息时发生错误,无法查找到改用与余额信息,用户id:{}", loginUserId);
            throw new CommonException("该用户钱包数据有误,请联系管理人员");
        }

        // 更新银行卡信息
        balance.setBankName(modifyBankInfoParam.getBankName());
        balance.setBankAccount(modifyBankInfoParam.getBankAccount());
        balance.setOpeningBank(modifyBankInfoParam.getOpeningBank());
        balance.setRecipient(modifyBankInfoParam.getRecipient());

        // 保存或更新记录
        h5ProfitShareBalanceService.updateById(balance);

        log.info("用户{}银行卡信息更新成功：银行名称={}, 卡号={}",
                loginUserId,
                modifyBankInfoParam.getBankName(),
                modifyBankInfoParam.getBankAccount());
    }

    @Override
    @Transactional
    public void withdraw(WithDrawParam withDrawParam) {
        // 获取当前登录用户ID
        String loginUserId = StpUtil.getLoginIdAsString();

        // 1. 从余额表查询用户信息进行校验
        LambdaQueryWrapper<H5ProfitShareBalance> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(H5ProfitShareBalance::getSharePartyId, loginUserId);
        H5ProfitShareBalance balance = h5ProfitShareBalanceService.getOne(queryWrapper);

        if (ObjUtil.isEmpty(balance)) {
            log.error("提现失败，无法查找到用户余额信息，用户ID: {}", loginUserId);
            throw new CommonException("该用户钱包数据有误，请联系管理人员");
        }

        // 2. 检查银行卡信息是否完整
        if (StrUtil.isBlank(balance.getBankAccount()) ||
                StrUtil.isBlank(balance.getBankName()) ||
                StrUtil.isBlank(balance.getRecipient()) ||
                StrUtil.isBlank(balance.getOpeningBank())) {
            throw new CommonException("银行卡信息不完整，请先完善银行卡信息");
        }

        // 3. 校验提现金额是否合法
        BigDecimal withdrawAmount = withDrawParam.getAmount();
        // 校验余额是否足够
        BigDecimal availableBalance = balance.getAvailableBalance() != null ?
                balance.getAvailableBalance() : BigDecimal.ZERO;

        if (withdrawAmount.compareTo(availableBalance) > 0) {
            throw new CommonException("提现金额不得大于可用余额");
        }

        // 4. 扣减余额
        BigDecimal newBalance = availableBalance.subtract(withdrawAmount);
        balance.setAvailableBalance(newBalance);
        balance.setLastUpdateTime(new Date());

        // 更新余额
        boolean updateResult = h5ProfitShareBalanceService.updateById(balance);
        if (!updateResult) {
            log.error("更新余额失败，用户ID: {}, 提现金额: {}", loginUserId, withdrawAmount);
            throw new CommonException(" 余额扣减失败，请重试");
        }

        // 5. 生成提现记录
        H5ProfitShareWithdrawRecord withdrawRecord = new H5ProfitShareWithdrawRecord();
        withdrawRecord.setWithdrawCode("WD" + System.currentTimeMillis()); // 生成提现单号
        withdrawRecord.setOrgId(balance.getOrgId());
        withdrawRecord.setSharePartyId(balance.getSharePartyId());
        withdrawRecord.setSharePartyName(balance.getSharePartyName());
        withdrawRecord.setBankName(balance.getBankName());
        withdrawRecord.setBankAccountName(balance.getOpeningBank());
        withdrawRecord.setBankAccountNumber(balance.getBankAccount());
        withdrawRecord.setWithdrawAmount(withdrawAmount);
        withdrawRecord.setFeeAmount(BigDecimal.ZERO); // 暂时不计算手续费
        withdrawRecord.setActualAmount(withdrawAmount); // 实际到账金额
        withdrawRecord.setApplyTime(new Date());
        withdrawRecord.setStatus("0"); // 1:待审核

        boolean saveWithdrawResult = withdrawRecordService.save(withdrawRecord);
        if (!saveWithdrawResult) {
            log.error("保存提现记录失败，用户ID: {}", loginUserId);
            // 这里可以考虑回滚之前的操作
            throw new CommonException("提现记录生成失败，请重试");
        }

        // 6. 生成分润余额变动记录（BIZ_PROFIT_SHARE_BALANCE_LOG表），使用提现记录的主键ID作为关联ID
        H5ProfitShareBalanceLog balanceLog = new H5ProfitShareBalanceLog();
        balanceLog.setOrgId(balance.getOrgId());
        balanceLog.setSharePartyId(balance.getSharePartyId());
        balanceLog.setSharePartyName(balance.getSharePartyName());
        balanceLog.setTradeType("2"); // 2-提现
        balanceLog.setChangeAmount(withdrawAmount.negate()); // 负值表示扣减
        balanceLog.setBeforeBalance(availableBalance);
        balanceLog.setAfterBalance(newBalance);
        balanceLog.setTradeTime(new Date());
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        balanceLog.setRemark("用户提现扣减 - " + dateFormat.format(new Date()));
        balanceLog.setRelationId(withdrawRecord.getId()); // 使用提现记录的主键ID作为关联ID

        boolean saveBalanceLogResult = h5ProfitShareBalanceLogService.save(balanceLog);
        if (!saveBalanceLogResult) {
            log.error("保存分润余额变动记录失败，用户ID: {}", loginUserId);
            throw new CommonException("保存分润余额变动记录失败，请重试");
        }
        log.info("用户提现申请提交成功，用户ID: {}, 提现金额: {}, 提现单号: {}",
                loginUserId, withdrawAmount, withdrawRecord.getWithdrawCode());
    }

    @Override
    public WithdrawRecordPage getWithdrawRecords(WithdrawRecordParam param) {
        WithdrawRecordPage result = new WithdrawRecordPage();

        // 获取当前登录用户ID
        String loginUserId = StpUtil.getLoginIdAsString();

        // 构建查询条件 - 使用提现记录表 H5ProfitShareWithdrawRecord
        LambdaQueryWrapper<H5ProfitShareWithdrawRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(H5ProfitShareWithdrawRecord::getSharePartyId, loginUserId)
                .orderByDesc(H5ProfitShareWithdrawRecord::getApplyTime);

        // 先构建总数查询条件
        LambdaQueryWrapper<H5ProfitShareWithdrawRecord> countQueryWrapper = new LambdaQueryWrapper<>();
        countQueryWrapper.eq(H5ProfitShareWithdrawRecord::getSharePartyId, loginUserId);

        // 根据参数添加过滤条件
        if (param.getLastId() != null && !param.getLastId().isEmpty()) {
            queryWrapper.lt(H5ProfitShareWithdrawRecord::getId, param.getLastId());
        }

        if (param.getTradeStatus() != null && !param.getTradeStatus().isEmpty()) {
            queryWrapper.eq(H5ProfitShareWithdrawRecord::getStatus, param.getTradeStatus());
            countQueryWrapper.eq(H5ProfitShareWithdrawRecord::getStatus, param.getTradeStatus());
        }

        // 日期筛选：前端传来的是string，需要转化为Date再查询
        if (param.getStartTime() != null && !param.getStartTime().isEmpty() &&
                param.getEndTime() != null && !param.getEndTime().isEmpty()) {
            try {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                Date startDate = dateFormat.parse(param.getStartTime());
                Date endDate = dateFormat.parse(param.getEndTime());
                queryWrapper.ge(H5ProfitShareWithdrawRecord::getApplyTime, startDate)
                        .le(H5ProfitShareWithdrawRecord::getApplyTime, endDate);
                countQueryWrapper.ge(H5ProfitShareWithdrawRecord::getApplyTime, startDate)
                        .le(H5ProfitShareWithdrawRecord::getApplyTime, endDate);
            } catch (Exception e) {
                log.error("日期格式转换错误，startTime: {}, endTime: {}", param.getStartTime(), param.getEndTime(), e);
            }
        }

        // 查询符合条件的提现记录
        List<H5ProfitShareWithdrawRecord> withdrawRecordList = withdrawRecordService.list(queryWrapper);

        //查询数据条数（排除提现失败状态）
        countQueryWrapper.ne(H5ProfitShareWithdrawRecord::getStatus, "1"); // 排除状态为1（失败）的记录
        long total = withdrawRecordService.count(countQueryWrapper);
        result.setTotal((int) total);

        // 计算累计提现金额（排除失败状态的记录）
        BigDecimal cumulative = withdrawRecordList.stream()
                .filter(record -> !"1".equals(record.getStatus())) // 排除状态为1（失败）的记录
                .map(H5ProfitShareWithdrawRecord::getWithdrawAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 设置累计金额并格式化
        result.setCumulative(cumulative.setScale(2, BigDecimal.ROUND_HALF_UP));

        // 转换为VO列表
        List<WithdrawRecordVo> withdrawRecordVoList = withdrawRecordList.stream().map(record -> {
            WithdrawRecordVo vo = new WithdrawRecordVo();
            vo.setId(record.getId());
            // 银行名称后面添加银行卡号后四位
            if (record.getBankAccountNumber() != null && record.getBankAccountNumber().length() >= 4) {
                String lastFourDigits = record.getBankAccountNumber().substring(record.getBankAccountNumber().length() - 4);
                vo.setBankName(record.getBankName() + " (" + lastFourDigits + ")");
            } else {
                vo.setBankName(record.getBankName());
            }
            vo.setAmount(record.getWithdrawAmount() != null ?
                    record.getWithdrawAmount().setScale(2, BigDecimal.ROUND_HALF_UP) :
                    BigDecimal.ZERO.setScale(2));
            vo.setTradeStatus(record.getStatus()); // 状态直接返回数字：1-申请中 2-成功 3-失败

            // 设置申请时间（字符串格式）
            if (record.getApplyTime() != null) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                vo.setApplyTime(dateFormat.format(record.getApplyTime()));
            }

            // 使用switch整合完成时间和提现信息
            String message;
            switch (record.getStatus()) {
                case "0":
                    vo.setWithdrawMessage("提现申请已提交，等待审核");
                    break;
                case "1":
                    message = "审核失败";
                    if (StrUtil.isNotBlank(record.getAuditRemark())) {
                        message += "，原因：" + record.getAuditRemark();
                    }
                    vo.setWithdrawMessage(message);
                    break;
                case "2":
                    vo.setWithdrawMessage("审核通过，等待工作人员打款");
                    break;
                case "3":
                    message = "打款成功";
                    if (record.getPayTime() != null) {
                        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        String time = dateFormat.format(record.getPayTime());
                        message += ",已于" + time + "打款";
                    }
                    vo.setWithdrawMessage(message);
                    break;
            }

            vo.setWithdrawNo(record.getWithdrawCode());
            vo.setDealer(record.getAuditUser() != null ? record.getAuditUser() : "系统自动处理"); // 处理人

            return vo;
        }).collect(Collectors.toList());

        result.setList(withdrawRecordVoList);

        return result;
    }

}
